/**
 * 
 */
package com.monkeyboy.security.authentication.mobile;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;

import com.monkeyboy.security.authentication.MyAuthenticationFailureHandler;
import com.monkeyboy.security.filter.ValidateCodeException;

/**
 * 在短信验证登录之前先验证短信验证码是否有效
 * @Description
 * @author Gavin<br>
 *         2019年8月25日
 */
@Component("smsValidateCodeFilter")
public class SmsValidateCodeFilter extends OncePerRequestFilter implements InitializingBean {
	@Autowired
	private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
	private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
	/**
	 * 验证请求url与配置的url是否匹配的工具类
	 */
	private AntPathMatcher pathMatcher = new AntPathMatcher();
	private String[] urls;

	/**
	 * 初始化要拦截的url配置信息
	 */
	@Override
	public void afterPropertiesSet() throws ServletException {
		super.afterPropertiesSet();
		// 初始化bean后需要做的哪些事情，这儿可以初始化要拦截的url信息，这儿写死方便测试，线上环境通过配置文件引入需要过滤的路径，支持配置
		urls = new String[] { "/authentication/mobile" };
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.web.filter.OncePerRequestFilter#doFilterInternal(javax.
	 * servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
	 * javax.servlet.FilterChain)
	 */
	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		if (StringUtils.equalsIgnoreCase(request.getMethod(), "post")) {
			try {
				for (String url : urls) {
					if (pathMatcher.match(url, request.getRequestURI())) {
						logger.error("验证码路径匹配符合");
						validate(new ServletWebRequest(request));
					}
				}
			} catch (ValidateCodeException e) {// 捕捉验证码异常
				e.printStackTrace();
				myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);
				return;// 验证不通过就需要返回，否则还是会执行后面的过滤链
			}
		}
		// 这里需要放行，才会继续执行下一步过滤链的过滤操作
		filterChain.doFilter(request, response);

	}

	/**
	 * @throws ServletRequestBindingException
	 * @Description<br>
	 *
	 *                  <pre>
	 *	 {@code
	 *		
	 *	 }
	 *                  </pre>
	 * 
	 * @Author Gavin</br>
	 *         2019年8月25日
	 */
	private void validate(ServletWebRequest request) throws ServletRequestBindingException {
		// 从session中获取到存入进去的验证码
		String smsInSession = (String) sessionStrategy.getAttribute(request, "smsCode");
		// 获取到页面传递过来的验证码
		String smsInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), "smsCode");
		// 这儿把验证码写死以便测试
		smsInSession = "123456";
		if (StringUtils.isBlank(smsInRequest)) {
			throw new ValidateCodeException("短信验证码不能为空！");
		}
		if (!StringUtils.equals(smsInSession, smsInRequest)) {
			throw new ValidateCodeException("短信验证码不匹配");
		}
		sessionStrategy.removeAttribute(request, "smsCode");// 验证完后移除session中的验证码
	}

}
